package com.hjk.waibao.mj.controller;

import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.MD5;
import cn.hutool.poi.excel.ExcelWriter;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.hjk.waibao.mj.annotation.PostPara;
import com.hjk.waibao.mj.bean.ApiResult;
import com.hjk.waibao.mj.common.model.AuthorizeCode;
import com.hjk.waibao.mj.common.model.AuthorizeCodeLoginHistory;
import com.jfinal.core.Controller;
import com.jfinal.core.paragetter.Para;
import com.jfinal.json.Json;
import com.jfinal.kit.PropKit;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Page;
import org.apache.log4j.Logger;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import static com.hjk.waibao.mj.bean.ApiResult.*;

/**
 * 本 demo 仅表达最为粗浅的 jfinal 用法，更为有价值的实用的企业级用法
 * 详见 JFinal 俱乐部: http://jfinal.com/club
 * <p>
 * IndexController
 */
public class AuthorizeCodeController extends Controller {
    private static Logger logger = Logger.getLogger(AuthorizeCodeController.class);
    public static String adminId = PropKit.get("admin_id");


    public void list(@PostPara Integer pageSize, @PostPara Integer pageNumber, @PostPara Integer enabled,
                     @PostPara String code, @PostPara String notes,
                     @PostPara JSONArray createTime, @PostPara JSONArray expireTime) {
        String whereSql = " where 1=1 ";
        List<Object> paraList = new ArrayList<>();
        if (enabled != null) {
            whereSql += " and enabled = ?";
            paraList.add(enabled);
        }
        if (code != null) {
            whereSql += " and code like ?";
            paraList.add("%" + code + "%");
        }
        if (notes != null) {
            whereSql += " and notes like ?";
            paraList.add("%" + notes + "%");
        }
        if (createTime != null && createTime.size() > 0) {
            whereSql += " and create_time >= ?";
            paraList.add(createTime.getString(0) + " 00:00:00");
            whereSql += " and create_time <= ?";
            paraList.add(createTime.getString(0) + " 23:59:59");
        }
        if (expireTime != null && expireTime.size() > 0) {
            whereSql += " and expire_time >= ?";
            paraList.add(expireTime.getString(0) + " 00:00:00");
            whereSql += " and expire_time <= ?";
            paraList.add(expireTime.getString(0) + " 23:59:59");
        }

        Page<AuthorizeCode> page = AuthorizeCode.dao.paginate(pageNumber, pageSize,
                "select *", " from t_authorize_code " + whereSql + " order by create_time desc",
                paraList.toArray(new Object[0]));
        renderJson(ApiResult.createSuccessWithJsonDataJson("", Json.getJson().toJson(page)));
    }

    public void generate(@PostPara String notes, @PostPara Integer num, @PostPara Date expireTime) {
        if (StrUtil.isBlankOrUndefined(notes)) {
            renderJson(ApiResult.createFail("必须填写备注"));
            return;
        }
        if (num == null || num <= 0) {
            renderJson(ApiResult.createFail("数量填写错误"));
            return;
        }
        if (expireTime == null) {
            expireTime = DateUtil.parseDate("2099-01-01");
        }
        List<AuthorizeCode> authorizeCodeList = new ArrayList<>();
        MD5 md5 = MD5.create();
        for (int i = 0; i < num; i++) {
            AuthorizeCode authorizeCode = new AuthorizeCode();
            authorizeCode.setCode(AuthorizeCode.generateCode());
            authorizeCode.setId(md5.digestHex(authorizeCode.getCode()));
            authorizeCode.setNotes(notes);
            authorizeCode.setCreateTime(new Date());
            authorizeCode.setEnabled(true);
            authorizeCode.setExpireTime(expireTime);
            authorizeCodeList.add(authorizeCode);
        }
        Db.batchSave(authorizeCodeList, 100);
        renderJson(ApiResult.createSuccess(authorizeCodeList));
    }

    public void validate(@PostPara String code, @PostPara String machineCode, @PostPara Boolean logoutOther) {
        code = code.trim();
        AuthorizeCode authorizeCode = AuthorizeCode.dao.findById(MD5.create().digestHex(code));
        if (authorizeCode == null) {
            renderJson(ApiResult.createJson(AUTHORIZE_CODE_NOT_FOUND_CODE, "不存在该授权码", null));
            return;
        }
        if (authorizeCode.getExpireTime().before(new Date())) {
            renderJson(ApiResult.createJson(AUTHORIZE_CODE_EXPIRE_CODE, "授权码已过期", null));
            return;
        }
        AuthorizeCodeLoginHistory authorizeCodeLoginHistory = AuthorizeCodeLoginHistory.dao.findFirst("select * from t_authorize_code_login_history where code_id = ? and logout_time is null limit 1", authorizeCode.getId());
        if (authorizeCodeLoginHistory != null) {
            if (!StrUtil.equals(machineCode, authorizeCodeLoginHistory.getMachineCode())) {
                if (logoutOther == null || !logoutOther) {
                    renderJson(ApiResult.createJson(AUTHORIZE_CODE_LOGGED_CODE, "授权码已登录", null));
                } else {
                    AuthorizeCodeLoginHistory newAuthorizeCodeLoginHistory = new AuthorizeCodeLoginHistory();
                    newAuthorizeCodeLoginHistory.setCodeId(authorizeCode.getId());
                    newAuthorizeCodeLoginHistory.setMachineCode(machineCode);
                    newAuthorizeCodeLoginHistory.setLoginTime(new Date());
                    authorizeCodeLoginHistory.setLogoutTime(new Date());
                    AuthorizeCodeLoginHistory finalAuthorizeCodeLoginHistory = authorizeCodeLoginHistory;
                    Db.tx(() -> {
                        finalAuthorizeCodeLoginHistory.update();
                        newAuthorizeCodeLoginHistory.save();
                        return true;
                    });
                    renderJson(ApiResult.createSuccess(null));
                }
            } else {
                renderJson(ApiResult.createSuccess(null));
            }
        } else {
            authorizeCodeLoginHistory = new AuthorizeCodeLoginHistory();
            authorizeCodeLoginHistory.setCodeId(authorizeCode.getId());
            authorizeCodeLoginHistory.setMachineCode(machineCode);
            authorizeCodeLoginHistory.setLoginTime(new Date());
            authorizeCodeLoginHistory.save();
            renderJson(ApiResult.createSuccess(null));
        }


    }

    public void disableAuthorizeCodeBatch(@PostPara com.alibaba.fastjson.JSONArray idList) {
        System.out.println(idList);
        Db.delete("update t_authorize_code set enabled=0 where id in (" + StrUtil.repeatAndJoin("?", idList.size(), ",") + ")", idList.toArray());
        renderJson(ApiResult.createSuccess(""));
    }

    public void enableAuthorizeCodeBatch(@PostPara com.alibaba.fastjson.JSONArray idList) {
        System.out.println(idList);
        Db.delete("update t_authorize_code set enabled=1 where id in (" + StrUtil.repeatAndJoin("?", idList.size(), ",") + ")", idList.toArray());
        renderJson(ApiResult.createSuccess(""));
    }

    public void codeStatus(@PostPara String code, @PostPara String machineCode) {
        code = code.trim();
        Integer exists = Db.queryInt("select 1 from t_authorize_code_login_history where code_id=? and machine_code=? and logout_time is null", MD5.create().digestHex(code), machineCode);
        if (exists != null) {
            renderJson(ApiResult.createSuccess(null));
        } else {
            renderJson(ApiResult.createJson(AUTHORIZE_CODE_MACHINE_LOGOUT_CODE, "授权码在其他服务器上激活，当前服务器授权失效，请检查是否授权码泄漏", null));
        }
    }

    public void exportExcel(@Para String condition) throws IOException {
        int batch = 3000;
        JSONObject conditionJson = JSONObject.parseObject(condition);
        Integer enabled = conditionJson.getInteger("enabled");
        String code = conditionJson.getString("code");
        String notes = conditionJson.getString("notes");
        JSONArray createTime = conditionJson.getJSONArray("createTime");
        JSONArray expireTime = conditionJson.getJSONArray("expireTime");
        String whereSql = " where 1=1 ";
        List<Object> paraList = new ArrayList<>();
        if (enabled != null) {
            whereSql += " and enabled =?";
            paraList.add(enabled);
        }
        if (code != null) {
            whereSql += " and code like ?";
            paraList.add("%" + code + "%");
        }
        if (notes != null) {
            whereSql += " and notes like ?";
            paraList.add("%" + notes + "%");
        }
        if (createTime != null && createTime.size() > 0) {
            whereSql += " and create_time >= ?";
            paraList.add(createTime.getString(0) + " 00:00:00");
            whereSql += " and create_time <= ?";
            paraList.add(createTime.getString(0) + " 23:59:59");
        }
        if (expireTime != null && expireTime.size() > 0) {
            whereSql += " and expire_time >= ?";
            paraList.add(expireTime.getString(0) + " 00:00:00");
            whereSql += " and expire_time <= ?";
            paraList.add(expireTime.getString(0) + " 23:59:59");
        }
        File tempFile = new File("授权码-" + DateUtil.format(new Date(), "yyyy_MM_dd_HH_mm_ss") + ".xlsx");
        System.out.println(tempFile.getAbsolutePath());
        try {
            ExcelWriter excelWriter = new ExcelWriter(tempFile);
            ArrayList<String> rowData = ListUtil.toList("授权码", "备注", "创建时间", "过期时间", "是否启用");
            excelWriter.writeRow(rowData);
            List<AuthorizeCode> authorizeCodeList = AuthorizeCode.dao.find("select * from t_authorize_code " + whereSql, paraList.toArray(new Object[0]));
            int i = 0;
            for (AuthorizeCode authorizeCode : authorizeCodeList) {
                ArrayList<Object> rowData1 = ListUtil.toList(
                        authorizeCode.getCode(), authorizeCode.getNotes(),
                        DateUtil.formatDateTime(authorizeCode.getCreateTime()),
                        DateUtil.formatDateTime(authorizeCode.getExpireTime()),
                        authorizeCode.getEnabled() ? "是" : "否");
                excelWriter.writeRow(rowData1);
            }
            excelWriter.flush();
            excelWriter.getSheet().setColumnWidth(1, 10000);
            excelWriter.getSheet().setColumnWidth(2, 5000);
            excelWriter.getSheet().setColumnWidth(3, 5000);
            excelWriter.getSheet().setColumnWidth(4, 5000);
            excelWriter.close();
            HttpServletResponse response = getResponse();
            response.setCharacterEncoding("UTF-8");
            response.setHeader("content-Type", "application/vnd.ms-excel");
            response.setHeader("Content-Disposition",
                    "attachment;filename=" + URLEncoder.encode("授权码-" + DateUtil.formatDate(new Date()), "UTF-8") + ".xlsx");
            ServletOutputStream outputStream = response.getOutputStream();
            for (byte b : FileUtil.readBytes(tempFile)) {
                outputStream.write(b);
            }
            outputStream.flush();

        } catch (Exception e) {
            e.printStackTrace();
            renderJson(ApiResult.createFail("导出失败"));
        } finally {
            try {
                tempFile.delete();
            } catch (Exception e) {

            }
        }
    }

    public void deleteBatch(@PostPara com.alibaba.fastjson.JSONArray idList) {
        System.out.println(idList);
        Db.delete("delete from t_authorize_code where id in (" + StrUtil.repeatAndJoin("?", idList.size(), ",") + ")", idList.toArray());
        renderJson(ApiResult.createSuccess(""));
    }

}



